package net.meosoft.maven.plugins;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

/**
 * Goal which creates a set of symbolic links.
 * CHECKSTYLE IGNORE Javadoc FOR NEXT 2 LINES
 * @goal create
 * @phase process-sources
 */
public final class CreateMojo extends AbstractMojo {
	/** Whether the system is Windows or not. */
	private static final boolean IS_WINDOWS = System.getProperty("os.name", "not-detected")
					.toLowerCase(Locale.getDefault()).contains("win");

	/**
	 * Ensures that the parent directory of a path exists.
	 * @param child
	 *            example child of the targeted parent folder
	 * @throws IOException
	 *             if the parent could not be created
	 */
	private static void doEnsureParentExists(final Path child) throws IOException {
		final Path parent = child.getParent();
		if (!Files.exists(parent)) {
			Files.createDirectories(parent);
		}
	}

	/**
	 * Create the target folder, if it does not exist.
	 * @parameter(default=value = "true")
	 * @since 1.0-SNAPSHOT
	 */
	private boolean createMissingTarget = true;

	/**
	 * Set of symbolic links to work with.
	 * @parameter
	 * @required
	 * @since 1.0-SNAPSHOT
	 */
	private List<SymlinkData> symlinks = new ArrayList<SymlinkData>();

	/**
	 * Executes the MOJO.
	 * @throws MojoExecutionException
	 *             when a link could not be created
	 */
	@Override
	public void execute() throws MojoExecutionException {
		// Ensure the list of symbolic links isn't empty.
		if (symlinks.isEmpty()) {
			getLog().info("No links were provided.");
			return;
		}

		for (final SymlinkData symlink : symlinks) {
			// Get the directories
			final Path link = Paths.get(symlink.getLink());
			final Path target = Paths.get(symlink.getTarget());

			// Ensure the parent folder of the link exists
			try {
				CreateMojo.doEnsureParentExists(link);
			} catch (final IOException e) {
				throw new MojoExecutionException("Unable to create parent of link folder.", e);
			}

			// Ensure the target folder exists.
			if (createMissingTarget && !Files.exists(target)) {
				try {
					Files.createDirectories(target);
				} catch (final IOException e) {
					throw new MojoExecutionException("Unable to create target directory.", e);
				}
			}

			// Output to the log our action
			getLog().info("Creating link: ".concat(link.toString()).concat(" -> ").concat(target.toString()));

			// Handle Windows differently to Linux
			try {
				if (CreateMojo.IS_WINDOWS) {
					getLog().debug(WinJunction.create(link.toFile(), target.toFile()));
				} else {
					Files.createSymbolicLink(link, target);
				}
			} catch (final IOException e) {
				throw new MojoExecutionException("Unable to create symbolic link.", e);
			}

			// Verify the symbolic link was created
			if (!link.toFile().getAbsoluteFile().exists()) {
				throw new MojoExecutionException("Unable to verify symbolic link was made: ".concat(link.toString()));
			}
		}
	}
	
	/**
	 * Default constructor.
	 */
	public CreateMojo() {
		super();
	}
}
